<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es6 class和函数类的区别</title>
  <!-- 
  在 JavaScript ES6 中，引入了  `class`  语法，使得定义类和创建对象的方式更加清晰和直观。与传统的函数构造器相比，ES6 的  `class`  语法有一些显著的区别。
  1. 定义方式
  - 函数构造器：
    使用函数定义构造器，并通过  `new`  关键字创建实例。
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }

    Person.prototype.sayHello = function() {
        console.log(`Hello, my name is ${this.name}`);
    };
  - ES6  `class` ：
    使用  `class`  关键字定义类，构造函数使用  `constructor`  方法。
   class Person {
        constructor(name, age) {
            this.name = name;
            this.age = age;
        }

        sayHello() {
            console.log(`Hello, my name is ${this.name}`);
        }
    }
  2. 语法简洁性

  - 函数构造器：
    需要手动设置原型链和构造函数指向，语法相对繁琐。

  - ES6  `class` ：
    语法更加简洁明了，原型方法直接定义在类内部，且自动绑定到原型上。

  3. 继承
  - 函数构造器：
    继承需要使用  `Object.create()`  方法手动设置原型。
    function Employee(name, age, job) {
        Person.call(this, name, age); // 调用父类构造函数
        this.job = job;
    }

    Employee.prototype = Object.create(Person.prototype);
    Employee.prototype.constructor = Employee;

    Employee.prototype.sayJob = function() {
        console.log(`I work as a ${this.job}`);
    };
  - ES6  `class` ：
    使用  `extends`  关键字实现继承，语法更为直观。
    class Employee extends Person {
        constructor(name, age, job) {
            super(name, age); // 调用父类构造函数
            this.job = job;
        }

        sayJob() {
            console.log(`I work as a ${this.job}`);
        }
    }
  4. 静态方法
  - 函数构造器：
    静态方法需要手动添加到构造函数上。
  function MathUtil() {}
    MathUtil.add = function(a, b) {
        return a + b;
    };
  - ES6  `class` ：
    使用  `static`  关键字定义静态方法，语法更为清晰。
    class MathUtil {
        static add(a, b) {
            return a + b;
        }
    }
  5. 访问修饰符
  - 函数构造器：
    没有内置的私有属性或方法的支持，通常使用命名约定（如  `_` ）来表示私有。

  - ES6  `class` ：
    ES2022 引入了私有字段（以  `#`  开头），可以实现真正的私有属性。
    class Person {
        #age; // 私有属性

        constructor(name, age) {
            this.name = name;
            this.#age = age;
        }

        getAge() {
            return this.#age; // 只能在类内部访问
        }
    }
  6. 总结
  ES6 的  `class`  提供了一种更清晰和简洁的方式来定义类和对象，相比传统的函数构造器， `class`  语法在语法简洁性、继承、静态方法和私有属性等方面都有显著的改进。理解这些区别对于掌握现代 JavaScript 的面向对象编程非常重要。
  -->
</head>
<body>

  <script>
    // function 定义类
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }

    Person.prototype.sayName = function () {
      console.log(`My name is ${this.name}`);
    };

    var p1 = new Person("Tom", 18)
    console.log(p1.__proto__ === Person.prototype)
    console.log(Person.prototype.constructor)
    console.log(typeof Person) // function

    // 不同点: 作为普通函数去调用
    Person("abc", 100) // 作为构造函数去调用

    // class 定义类
    class Animal {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }

      sayName() {
        console.log(`My name is ${this.name}`);
      }
    }

    var p2 = new Animal("kobe", 30)
    console.log(p2.__proto__ === Animal.prototype)
    console.log(Animal.prototype.constructor)
    console.log(typeof Animal)

    // 不同点: class定义的类, 不能作为一个普通的函数进行调用
    // Animal("cba", 0)

    
  </script>
  
</body>
</html>